package se.webbzon.boltzmann.object.geometry;

import java.awt.Color;

import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.worldobject.appearance.ConeAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.CubeAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.CylinderAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.EllipsoidAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.FloorAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.WallAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.XYPlaneAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.XZPlaneAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.YZPlaneAppearance3D;

public class GeometryAppearance {
	
	// The geometry used for this appearance
	private final GeometryEnum geometry;
	
	// Whatever the surface of the geometry is closed or not
	private final boolean open;
	
	// The number of divisions used for this geometry
	private final int divisions;
	
	// Whatever the surface of the geometry is closed or not
	private final boolean backfaced;
	
	// The name of the texture used for this geometry
	private final String textureSetName;
	
	// The 3d-appearance associated with this geometry appearance
	private final SimpleAppearance3D appearance;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new GeometryAppearance. **/
	public GeometryAppearance(	GeometryEnum geometry, 
								boolean open, int divisions, boolean backfaced,
								int renderingOrder, 
								String textureSetName,
								double textureIndex, double textureSpeed,
								double xLayer, double yLayer, double zLayer,
								Color blending, float transparency,
								double hRep, double vRep,
								double hOffset, double vOffset,
								double angle) {
		this.geometry = geometry;
		this.open = open;
		this.divisions = divisions;
		this.backfaced = backfaced;
		this.textureSetName = textureSetName;
	
		// Set the properties
		int properties = 0;
		if (transparency != 0)
			properties |= SimpleAppearance3D.TRANSPARENCY;
		if (xLayer != 0 || yLayer != 0 || zLayer != 0)
			properties |= SimpleAppearance3D.LAYERS;
		if (hRep != 1 || vRep != 1)
			properties |= SimpleAppearance3D.TEXTURE_REPEATING;
		if (hOffset != 0 || vOffset != 0)
			properties |= SimpleAppearance3D.TEXTURE_TRANSLATION;
		if (angle != 0)
			properties |= SimpleAppearance3D.TEXTURE_ROTATION;
		
		// Select the appearance
		switch (geometry) {
		case CONE: 
			appearance = new ConeAppearance3D(renderingOrder,properties,open,divisions,backfaced); 
			break;
		case CUBE: 
			appearance = new CubeAppearance3D(renderingOrder,properties,backfaced); 
			break;
		case CYLINDER: 
			appearance = new CylinderAppearance3D(renderingOrder,properties,open,divisions,backfaced); 
			break;
		case ELLIPSOID: 
			appearance = new EllipsoidAppearance3D(renderingOrder,properties,divisions,backfaced); 
			break;
		case FLOOR: 
			appearance = new FloorAppearance3D(renderingOrder,properties,backfaced); 
			break;
		case WALL: 
			appearance = new WallAppearance3D(renderingOrder,properties,backfaced); 
			break;
		case XYPLANE: 
			appearance = new XYPlaneAppearance3D(renderingOrder,properties,backfaced); 
			break;
		case XZPLANE: 
			appearance = new XZPlaneAppearance3D(renderingOrder,properties,backfaced); 
			break;
		case YZPLANE: 
			appearance = new YZPlaneAppearance3D(renderingOrder,properties,backfaced); 
			break;
		default:
			appearance = new XYPlaneAppearance3D();
		}
		
		// Set the texture
		if (!textureSetName.equals("")) {
			appearance.setTextureSet(Resources.getTextureSet(textureSetName));
			appearance.setTextureIndex(textureIndex);
			appearance.setTextureSpeed(textureSpeed);
		}
		
		// Set the layer
		if (isSet(properties,SimpleAppearance3D.LAYERS)) 
			appearance.setLayer(xLayer, yLayer, zLayer);
		
		// Set the color
		appearance.setColor(blending);
		
		// Set the transparency
		if (isSet(properties,SimpleAppearance3D.TRANSPARENCY))
			appearance.setTransparency(transparency);
		
		// Set the texture repeating
		if (isSet(properties,SimpleAppearance3D.TEXTURE_REPEATING)) {
			appearance.setHRep(hRep);
			appearance.setVRep(vRep);
		}
		
		// Set the texture offset
		if (isSet(properties,SimpleAppearance3D.TEXTURE_TRANSLATION)) {
			appearance.setHOffset(hOffset);
			appearance.setVOffset(vOffset);
		}
		
		// Set the rotation
		if (isSet(properties,SimpleAppearance3D.TEXTURE_ROTATION))
			appearance.setRotation(angle);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns the geometry used for this geometry appearance. **/
	public GeometryEnum getGeometry() {
		return geometry;
	}
	
	/** Returns whatever the surface of the geometry is closed or not. **/
	public boolean isOpen() {
		return open;
	}

	/** Returns the number of divisions used for this geometry. **/
	public int getDivisions() {
		return divisions;
	}
	
	/** Returns whatever the surface of the geometry is back-faced or not. **/
	public boolean isBackfaced() {
		return backfaced;
	}
	
	/** Returns the name of the texture set used for this geometry appearance. **/
	public String getTextureSetName() {
		return textureSetName;
	}

	/** Returns the 3d-appearance associated with this geometry appearance. **/
	public SimpleAppearance3D getAppearance() {
		return appearance;
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns true if the given property is set in the given properties. **/
	private static final boolean isSet(int properties, int property) {
		return ((properties & property) == property);
	}

}
